/*
 * This file is a part of the SWFer project.
 *
 * Copyright (C) 2012 Michael Bradshaw <mjbshaw@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

#include "SimpleSound.hpp"
#include "Encode.hpp"
#include "Tags.hpp"

#include <iterator>

namespace swfer
{

std::vector<Packet> encode(const SimpleSound& sound)
{
	std::vector<Packet> v;

	Tag<DEFINE_SOUND> t;
	t.id = 1; // TODO: how to assign a unique ID?
	t.format = sound.format;
	t.rate = sound.rate; // TODO: don't rely on enum values to be some magic number
	t.size = sound.size;
	t.type = sound.layout;
	t.sampleCount = sound.samples;

	if (sound.format == MP3)
	{
		t.record.mp3.seekSamples = sound.skip;
	}
	else if (sound.format == ADPCM)
	{
		// TODO: add this to the SimpleSound struct!
		//t.record.adpcm.codeSize = ???
	}

	t.data = sound.data;

	v.push_back(encode(t));

	/*
	if (!sound.className.empty())
	{
		Tag<DO_ABC> abc;
		abc.flags = 0; //abc.flags = ???
		//abc.name = ???
		abc.data.push_back(0x01); abc.data.push_back(0x00); // minor (0x0001)
		abc.data.push_back(0x2e); abc.data.push_back(0x00); // major (0x002e)

		// cpool_info
		abc.data.push_back(0x00); // int_count
		abc.data.push_back(0x00); // uint_count
		abc.data.push_back(0x00); // double_count
		abc.data.push_back(0x08); // string_count

		// TODO: assert className and packageName <= 255 chars
		// string table
		abc.data.push_back(sound.className.size()); // length
		std::copy(sound.className.begin(), sound.className.end(), std::back_inserter(abc.data));

		abc.data.push_back(sound.packageName.size());
		std::copy(sound.packageName.begin(), sound.packageName.end(), std::back_inserter(abc.data));
		
		abc.data.push_back(0x0B);
		std::copy_n("flash.media", 0x0b, std::back_inserter(abc.data));

		abc.data.push_back(0x05);
		std::copy_n("Sound", 0x05, std::back_inserter(abc.data));

		abc.data.push_back(0x06);
		std::copy_n("Object", 0x06, std::back_inserter(abc.data));

		abc.data.push_back(0x0f);
		std::copy_n("EventDispatcher", 0x0f, std::back_inserter(abc.data));

		abc.data.push_back(0x0c);
		std::copy_n("flash.events", 0xc, std::back_inserter(abc.data));


		abc.data.push_back(0x06); // namespace_count
		
		// namespace table
		abc.data.push_back(0x05); // kind
		abc.data.push_back(0x01); // name

		abc.data.push_back(0x16);
		abc.data.push_back(0x02);

		abc.data.push_back(0x16);
		abc.data.push_back(0x03);

		abc.data.push_back(0x18);
		abc.data.push_back(0x01);

		abc.data.push_back(0x16);
		abc.data.push_back(0x07);


		abc.data.push_back(0x00); // ns_set_count


		abc.data.push_back(0x05); // multiname_count

		// multiname table
		abc.data.push_back(0x07); // kind
		abc.data.push_back(0x02); // data (ns)
		abc.data.push_back(0x01); // data (name)

		abc.data.push_back(0x07);
		abc.data.push_back(0x03);
		abc.data.push_back(0x04);

		abc.data.push_back(0x07);
		abc.data.push_back(0x02);
		abc.data.push_back(0x05);

		abc.data.push_back(0x07);
		abc.data.push_back(0x05);
		abc.data.push_back(0x06);


		abc.data.push_back(0x03); // method_count

		// method table
		abc.data.push_back(0x00); // param_count
		abc.data.push_back(0x00); // return_type
		abc.data.push_back(0x02); // name
		abc.data.push_back(0x00); // flags

		abc.data.push_back(0x00);
		abc.data.push_back(0x00);
		abc.data.push_back(0x02);
		abc.data.push_back(0x00);

		abc.data.push_back(0x00);
		abc.data.push_back(0x00);
		abc.data.push_back(0x02);
		abc.data.push_back(0x00);


		abc.data.push_back(0x00); // metadata_count


		abc.data.push_back(0x01); // class_count

		// instance table
		abc.data.push_back(0x01); // name
		abc.data.push_back(0x02); // super_name
		abc.data.push_back(0x08); // flags
		abc.data.push_back(0x04); // protectedNs
		abc.data.push_back(0x00); // intrf_count
		abc.data.push_back(0x01); // iinit
		abc.data.push_back(0x00); // trait_count

		// class table
		abc.data.push_back(0x00); // cinit
		abc.data.push_back(0x00); // trait_count


		abc.data.push_back(0x01); // script count

		//script table
		abc.data.push_back(0x02); // init
		abc.data.push_back(0x01); // trait_count
		abc.data.push_back(0x01); // trait[0].name
		abc.data.push_back(0x44); // trait[0].kind
		abc.data.push_back(0x01); // trait[0].data (slot_id)
		abc.data.push_back(0x00); // trait[0].data (classi)
		abc.data.push_back(0x00); // metadata_count


		abc.data.push_back(0x03); // method_body_count
		
		// method body table
		abc.data.push_back(0x00); // method
		abc.data.push_back(0x01); // max_stack
		abc.data.push_back(0x01); // local_count
		abc.data.push_back(0x05); // init_scope_depth
		abc.data.push_back(0x06); // max_scope_depth
		abc.data.push_back(0x03); // code_length
		abc.data.push_back(char(0xD0)); // code
		abc.data.push_back(0x30); // code
		abc.data.push_back(0x47); // code
		abc.data.push_back(0x00); // exception_count
		abc.data.push_back(0x00); // trait_count

		abc.data.push_back(0x01);
		abc.data.push_back(0x01);
		abc.data.push_back(0x01);
		abc.data.push_back(0x06);
		abc.data.push_back(0x07);
		abc.data.push_back(0x06);
		abc.data.push_back(char(0xD0));
		abc.data.push_back(0x30);
		abc.data.push_back(char(0xD0));
		abc.data.push_back(0x49);
		abc.data.push_back(0x00);
		abc.data.push_back(0x47);
		abc.data.push_back(0x00);
		abc.data.push_back(0x00);

		abc.data.push_back(0x02);
		abc.data.push_back(0x02);
		abc.data.push_back(0x01);
		abc.data.push_back(0x01);
		abc.data.push_back(0x05);
		abc.data.push_back(0x1f);
		abc.data.push_back(char(0xD0));
		abc.data.push_back(0x30);
		abc.data.push_back(0x65);
		abc.data.push_back(0x00);
		abc.data.push_back(0x5D);
		abc.data.push_back(0x03);
		abc.data.push_back(0x66);
		abc.data.push_back(0x03);
		abc.data.push_back(0x30);
		abc.data.push_back(0x5D);
		abc.data.push_back(0x04);
		abc.data.push_back(0x66);
		abc.data.push_back(0x04);
		abc.data.push_back(0x30);
		abc.data.push_back(0x5D);
		abc.data.push_back(0x02);
		abc.data.push_back(0x66);
		abc.data.push_back(0x02);
		abc.data.push_back(0x30);
		abc.data.push_back(0x5D);
		abc.data.push_back(0x02);
		abc.data.push_back(0x66);
		abc.data.push_back(0x02);
		abc.data.push_back(0x58);
		abc.data.push_back(0x00);
		abc.data.push_back(0x1D);
		abc.data.push_back(0x1D);
		abc.data.push_back(0x1D);
		abc.data.push_back(0x68);
		abc.data.push_back(0x01);
		abc.data.push_back(0x47);
		abc.data.push_back(0x00);
		abc.data.push_back(0x00);

		v.push_back(encode(abc));
	}
	*/

	Tag<SYMBOL_CLASS> s;
	Tag<SYMBOL_CLASS>::Symbol symbol;
	symbol.name = sound.className;
	symbol.tag = 1; // TODO: what should the symbol tag be?
	s.symbols.push_back(symbol);
	v.push_back(encode(s));

	return v;
}

}

/*
Original:
minor: 0x0001
major: 0x002e

cpool_info:
int_count: 0x00
uint_count: 0x00
double_count: 0x00
string_count: 0x0d (13) (string count + 1)
string[0]: (not present in abcFiles)
string[1]: 0x0a and "MyMusicWav" (0x4D 79 4D 75 73 69 63 57 61 76)
string[2]: 0x00 and nothing
string[3]: 0x0B and "flash.media"(0x66 6C 61 73 68 2E 6D 65 64 69 61)
string[4]: 0x05 and "Sound" (0x53 6F 75 6E 64)
string[5]: 0x06 and "Object" (0x4F 62 6A 65 63 74)
string[6]: 0x0f and "EventDispatcher" (0x45 76 65 6E 74 44 69 73 70 61 74 63 68 65 72)
string[7]: 0x0c and "flash.events" (0x66 6C 61 73 68 2E 65 76 65 6E 74 73)
string[8]: 0x17 and "__go_to_definition_help" (0x5F 5F 67 6F 5F 74 6F 5F 64 65 66 69 6E 69 74 69 6F 6E 5F 68 65 6C 70)
string[9]: 0x04 and "file" (0x66 69 6C 65)
string[10]: 0x0f and "/Users/mjbshaw/" (0x2F 55 73 65 72 73 2F 6D 6A 62 73 68 61 77 2F)
string[11]: 0x03 and "pos" (0x70 6F 73)
string[12]: 0x01 and "0" (0x30)

namespace_count: 0x06
namespace[0]: (not present in abcFiles)
namespace[1]: kind: 0x05 name: 0x01
namespace[2]: kind: 0x16 name: 0x02
namespace[3]: kind: 0x16 name: 0x03
namespace[4]: kind: 0x18 name: 0x01
namespace[5]: kind: 0x16 name: 0x07

ns_set_count: 0x00

multiname_count: 0x05
multiname[0]: (not present in abcFiles)
multiname[1]: kind: 0x07 data: 0x02 01 (ns: 0x02 name: 0x01)
multiname[2]: kind: 0x07 data: 0x03 04 (ns: 0x03 name: 0x04)
multiname[3]: kind: 0x07 data: 0x02 05 (ns: 0x02 name: 0x05)
multiname[4]: kind: 0x07 data: 0x05 06 (ns: 0x05 name: 0x06)



method_count: 0x03
method[0]: param_count: 0x00 return_type: 0x00 name: 0x02 flags: 0x00
method[1]: param_count: 0x00 return_type: 0x00 name: 0x02 flags: 0x00
method[2]: param_count: 0x00 return_type: 0x00 name: 0x02 flags: 0x00


metadata_count: 0x01
metadata[0]: name: 0x08 item_count: 0x02 items[0].key: 0x09 items[0].value: 0x0b items[1].key: 0x0a items[1].value: 0x0c


class_count: 0x01
instance[0]: name: 0x01 super_name: 0x02 flags: 0x08 protectedNs: 0x04 intrf_cout: 0x00 iinit:0x01 trait_count: 0x00
class[0]: cinit: 0x00 trait_count: 0x00


script_count: 0x01
script[0]: init: 0x02 trait_count: 0x01 trait[0].name: 0x01 trait[0].kind: 0x44 trait[0].data: 0x01 00 (slot_id: 0x01 classi: 0x00) metadata_count: 0x01 metadata[0]: 0x00


method_body_count: 0x03
method_body[0]: method: 0x00 max_stack: 0x01 local_count: 0x01 init_scope_depth: 0x05 max_scope_depth: 0x06 code_length: 0x03 code: 0xD0 30 47 exception_count: 0x00 trait_count: 0x00
method_body[1]: method: 0x01 max_stack: 0x01 local_count: 0x01 init_scope_depth: 0x06 max_scope_depth: 0x07 code_length: 0x06 code: 0xD0 30 D0 49 00 47 exception_count: 0x00 trait_count: 0x00
method_body[2]: method: 0x02 max_stack: 0x02 local_count: 0x01 init_scope_depth: 0x01 max_scope_depth: 0x05 code_length: 0x1f code: 0xD0 30 65 00 5D 03 66 03 30 5D 04 66 04 30 5D 02 66 02 30 5D 02 66 02 58 00 1D 1D 1D 68 01 47 exception_count: 0x00 trait_count: 0x00
*/

/*
Condensed:
minor: 0x0001
major: 0x002e

cpool_info:
int_count: 0x00
uint_count: 0x00
double_count: 0x00
string_count: 0x08
string[0]: (not present in abcFiles)
string[1]: 0x0a and "MyMusicWav" (0x4D 79 4D 75 73 69 63 57 61 76)
string[2]: 0x00 and nothing (NOTE: SEEMS TO BE PACKAGE NAME)
string[3]: 0x0B and "flash.media"(0x66 6C 61 73 68 2E 6D 65 64 69 61)
string[4]: 0x05 and "Sound" (0x53 6F 75 6E 64)
string[5]: 0x06 and "Object" (0x4F 62 6A 65 63 74)
string[6]: 0x0f and "EventDispatcher" (0x45 76 65 6E 74 44 69 73 70 61 74 63 68 65 72)
string[7]: 0x0c and "flash.events" (0x66 6C 61 73 68 2E 65 76 65 6E 74 73)

namespace_count: 0x06
namespace[0]: (not present in abcFiles)
namespace[1]: kind: 0x05 name: 0x01
namespace[2]: kind: 0x16 name: 0x02
namespace[3]: kind: 0x16 name: 0x03
namespace[4]: kind: 0x18 name: 0x01
namespace[5]: kind: 0x16 name: 0x07

ns_set_count: 0x00

multiname_count: 0x05
multiname[0]: (not present in abcFiles)
multiname[1]: kind: 0x07 data: 0x02 01 (ns: 0x02 name: 0x01)
multiname[2]: kind: 0x07 data: 0x03 04 (ns: 0x03 name: 0x04)
multiname[3]: kind: 0x07 data: 0x02 05 (ns: 0x02 name: 0x05)
multiname[4]: kind: 0x07 data: 0x05 06 (ns: 0x05 name: 0x06)


method_count: 0x03
method[0]: param_count: 0x00 return_type: 0x00 name: 0x02 flags: 0x00
method[1]: param_count: 0x00 return_type: 0x00 name: 0x02 flags: 0x00
method[2]: param_count: 0x00 return_type: 0x00 name: 0x02 flags: 0x00


metadata_count: 0x00


class_count: 0x01
instance[0]: name: 0x01 super_name: 0x02 flags: 0x08 protectedNs: 0x04 intrf_cout: 0x00 iinit:0x01 trait_count: 0x00
class[0]: cinit: 0x00 trait_count: 0x00


script_count: 0x01
script[0]: init: 0x02 trait_count: 0x01 trait[0].name: 0x01 trait[0].kind: 0x44 trait[0].data: 0x01 00 (slot_id: 0x01 classi: 0x00) metadata_count: 0x00


method_body_count: 0x03
method_body[0]: method: 0x00 max_stack: 0x01 local_count: 0x01 init_scope_depth: 0x05 max_scope_depth: 0x06 code_length: 0x03 code: 0xD0 30 47 exception_count: 0x00 trait_count: 0x00
method_body[1]: method: 0x01 max_stack: 0x01 local_count: 0x01 init_scope_depth: 0x06 max_scope_depth: 0x07 code_length: 0x06 code: 0xD0 30 D0 49 00 47 exception_count: 0x00 trait_count: 0x00
method_body[2]: method: 0x02 max_stack: 0x02 local_count: 0x01 init_scope_depth: 0x01 max_scope_depth: 0x05 code_length: 0x1f code: 0xD0 30 65 00 5D 03 66 03 30 5D 04 66 04 30 5D 02 66 02 30 5D 02 66 02 58 00 1D 1D 1D 68 01 47 exception_count: 0x00 trait_count: 0x00
*/


/*
write(0x0001) // minor
write(0x002e) // major

write(0x00)
write(0x00)
write(0x00)
write(0x08)
write(className.size())
write(className)

write(packageName.size())
write(packageName)

write(0x0B)
write("flash.media")

write(0x05)
write("Sound")

write(0x06)
write("Object")

write(0x0f)
write("EventDispatcher")

write(0x0c)
write("flash.events")

write(0x06)
write(0x05)
write(0x01)

write(0x16)
write(0x02)

write(0x16)
write(0x03)

write(0x18)
write(0x01)

write(0x16)
write(0x07)


write(0x00)


write(0x05)
write(0x07)
write(0x02)
write(0x01)

write(0x07)
write(0x03)
write(0x04)

write(0x07)
write(0x02)
write(0x05)

write(0x07)
write(0x05)
write(0x06)


write(0x03)
write(0x00)
write(0x00)
write(0x02)
write(0x00)

write(0x00)
write(0x00)
write(0x02)
write(0x00)

write(0x00)
write(0x00)
write(0x02)
write(0x00)


write(0x00)


write(0x01)
write(0x01)
write(0x02)
write(0x08)
write(0x04)
write(0x00)
write(0x01)
write(0x00)
write(0x00)
write(0x00)


write(0x01)
write(0x02)
write(0x01)
write(0x01)
write(0x44)
write(0x01)
write(0x00)
write(0x00)


write(0x03)
method_body[0]: method: 0x00 max_stack: 0x01 local_count: 0x01 init_scope_depth: 0x05 max_scope_depth: 0x06 code_length: 0x03 code: 0xD0 30 47 exception_count: 0x00 trait_count: 0x00
method_body[1]: method: 0x01 max_stack: 0x01 local_count: 0x01 init_scope_depth: 0x06 max_scope_depth: 0x07 code_length: 0x06 code: 0xD0 30 D0 49 00 47 exception_count: 0x00 trait_count: 0x00
method_body[2]: method: 0x02 max_stack: 0x02 local_count: 0x01 init_scope_depth: 0x01 max_scope_depth: 0x05 code_length: 0x1f code: 0xD0 30 65 00 5D 03 66 03 30 5D 04 66 04 30 5D 02 66 02 30 5D 02 66 02 58 00 1D 1D 1D 68 01 47 exception_count: 0x00 trait_count: 0x00
*/